package org.example.judge_admin.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.judge_admin.service.MyFileService;
import org.example.judge_admin.service.SessionService;
import org.example.judge_admin.service.UserService;
import org.example.judge_admin.service.impl.UserServiceImpl;
import org.example.judge_common.annotation.AuthAnnotation;
import org.example.judge_common.entity.PageResult;
import org.example.judge_common.entity.RequestParams;
import org.example.judge_common.entity.RequestUserParams;
import org.example.judge_common.entity.ResponseResult;
import org.example.judge_common.properties.JudgeProperties;
import org.example.judge_common.util.IdWorker;
import org.example.judge_common.util.MyUtils;
import org.example.judge_pojo.Auth;
import org.example.judge_pojo.MyFile;
import org.example.judge_pojo.Session;
import org.example.judge_pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;

@Controller
@CrossOrigin
@Slf4j
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IdWorker idWorker;
    @Qualifier("UserServiceImpl")
    @Autowired
    private UserService userService;

    @Qualifier("SessionServiceImpl")
    @Autowired
    private SessionService sessionService;
    @Qualifier("MyFileServiceImpl")
    @Autowired
    private MyFileService myFileService;

    @Autowired
    private JudgeProperties judgeProperties;

    @PostMapping("/search")
    @AuthAnnotation({Auth.ADMINISTRATOR})
    @ResponseBody
    public ResponseResult search(RequestUserParams params){
        PageResult<User> search = userService.search(params);
        return ResponseResult.success().setData(search);

    }

    @PostMapping("/save")
    @AuthAnnotation({Auth.ROOT})
    @ResponseBody
    public ResponseResult save(@RequestBody User user,HttpServletRequest request){
        user.setId(idWorker.nextId().toString());
        if (MyUtils.isEmpty(user.getAvatarId())) {
            MultipartFile file = MyUtils.getImage(user.getUsername());
            ResponseResult upload = this.upload(file, request);
            if(upload.isSuccess()){
                user.setAvatarId(upload.getData().toString());
            }else log.error("生成系统头像失败，错误信息：{}",upload.getMessage());
        }
        userService.save(user);
        return ResponseResult.success();
    }


    @PutMapping("/update")
    @AuthAnnotation(Auth.ROOT)
    @ResponseBody
    public ResponseResult updateById(@RequestBody User user,HttpServletRequest request){
        if(MyUtils.isEmpty(user.getId())){

            User loginUser = (User) request.getAttribute("loginUser");
            log.warn("用户Id：{}:{}试图修改没有ID的用户信息",loginUser.getId(),loginUser.getUsername());
            return ResponseResult.fail("用户ID不能为空");
        }
        userService.updateById(user);
        return ResponseResult.success();
    }

    /**
     * 只能修改简单的信息 => username,school,course,description,phone,sex
     * @param user
     * @param request
     * @return
     */
    @PutMapping("/loginUpdate")
    @AuthAnnotation(Auth.CLIENT)
    @ResponseBody
    public ResponseResult loginUpdateById(@RequestBody User user,HttpServletRequest request){
        if(MyUtils.isEmpty(user.getId())){
            return ResponseResult.fail("用户ID不能为空");
        }
        User loginUser = (User) request.getAttribute("loginUser");
        if(!loginUser.getId().equals(user.getId())){
            return ResponseResult.unAuditor();
        }
        User entity = new User();
        entity.setUsername(user.getUsername());
        entity.setId(user.getId());
        entity.setSchool(user.getSchool());
        entity.setCourse(user.getCourse());
        entity.setDescription(user.getDescription());
        entity.setPhone(user.getPhone());
        entity.setSex(user.getSex());
        if(MyUtils.isNotEmpty(user.getAvatarId()))entity.setAvatarId(user.getAvatarId());
        User usernameOne = userService.getUsernameOne(entity.getUsername());
        if (usernameOne!=null&&!usernameOne.getId().equals(entity.getId())) {
            return ResponseResult.fail("用户名已存在");
        }
        userService.updateById(entity);
        return ResponseResult.success();
    }
    @DeleteMapping("/delete/{id}")
    @AuthAnnotation({Auth.ROOT})
    @ResponseBody
    public ResponseResult deleteById(@PathVariable("id")String id, HttpServletRequest request){
        User byId = userService.getById(id);
        if(byId==null)return ResponseResult.NotData();
        if(Auth.isAdmin(byId))return ResponseResult.fail("无法删除管理员账号");
        userService.removeById(id);
        log.info("用户ID：{}已被用户：{}删除",id, ((User) request.getAttribute("loginUser")).getUsername());
        return ResponseResult.success();
    }

    @PostMapping("/detail/{id}")
    @AuthAnnotation({Auth.CLIENT,"User_detail"})
    @ResponseBody
    public ResponseResult detail(@PathVariable("id") String id,HttpServletRequest request){
        User loginUser = (User) request.getAttribute("loginUser");
        //只有管理员或自己可以
        if(!Auth.isAdmin(loginUser,"User_detail")&&!loginUser.getId().equals(id))return ResponseResult.unAuditor();
        User byId = userService.getById(id);
        return ResponseResult.success().setData(byId);
    }



    /**
     * 阉割版的用户详情，包括用户名，学校，等信息
     * @param id
     * @return
     */
    @PostMapping("/easy/{id}")
    @AuthAnnotation({Auth.CLIENT,"User_easy"})
    @ResponseBody
    public ResponseResult detailEasy(@PathVariable("id") String id){
        User byId = userService.getById(id);
        if(byId==null)return ResponseResult.success();
        User user = new User();
        user.setUsername(byId.getUsername()); //用户名
        user.setSchool(byId.getSchool());     // 学校
        user.setSex(byId.getSex());           // 性别
        user.setCourse(byId.getCourse());     // 专业
        user.setAvatarId(byId.getAvatarId()); //头像
        user.setId(byId.getId());             // id
        user.setRating(byId.getRating());   //rating
        user.setDescription(byId.getDescription());
        return ResponseResult.success().setData(user);
    }

    //上传头像/文件
    @PostMapping("/upload")
    @ResponseBody
    public ResponseResult upload(MultipartFile file ,HttpServletRequest request){
        if(file==null)return ResponseResult.fail("错误文件");
        MyFile image = new MyFile();
        File dir = new File(judgeProperties.getDataDir(), "image");
        if(!dir.exists())dir.mkdirs();
        User loginUser = (User) request.getAttribute("loginUser");
        int i = file.getOriginalFilename().lastIndexOf(".");
        if(i==-1)return ResponseResult.fail("文件名称不符合规定");
        image.setType(file.getOriginalFilename().substring(i+1));
        image.setUserId(loginUser.getId());
        image.setName(file.getOriginalFilename());
        myFileService.save(image);
        try {
            file.transferTo(new File(dir,image.getId()+"."+image.getType()));
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseResult.fail("文件保存失败");
        }
        return ResponseResult.success().setData(image.getId());

    }
    //下载图片/文件
    @RequestMapping("/download/{id}")
    public void download(@PathVariable("id") String id, HttpServletResponse response) throws IOException {

        MyFile byId = myFileService.getById(id);
        File file = new File(judgeProperties.getDataDir(),"image");;
        if(byId==null){
            file = new File(file,"404.jpg");
            byId = new MyFile();
            byId.setType("jpg");
        }
        else file = new File(file,id+"."+byId.getType());
        FileInputStream inputStream = null;
        // 获取文件流
        try {
            // 获取文件流
            inputStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            log.warn("找不到文件{}，msg：{}",file,e.getMessage());
            return ;
        }
        // 响应输出流
        ServletOutputStream sos = null;
        try {
            //获取输出流
            sos = response.getOutputStream();
        } catch (IOException e) {
            log.warn("获取输出响应流失败，msg：{}",e.getMessage());
        }
        //判断文件类型
        if(!MyUtils.isImage(byId.getType())){  //文件不是图片，设置为下载
            log.warn("非图片文件{}，进入下载方式",file);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename="+byId.getId() + "." + byId.getType());
            // 创建缓冲区
            int len = 0;
            byte[] bytes = new byte[1000];
            //将fileOutputStream流写入到buffer缓冲区,并使用OutputStream将缓冲区中的数据输入到客户端
            while ((len = inputStream.read(bytes))>0){
                sos.write(bytes,0,len);
            }
            return ;
        }

        // 响应图片
        // 设置图片响应头
        response.setContentType("image/"+byId.getType());
        BufferedImage buffImg = null;
        try {
            //获取图片流
            buffImg = ImageIO.read(inputStream);
        } catch (IOException e) {
            log.warn("该图片{},使用BufferedImage读取失败,msg:{}",file,e.getMessage());
            return ;
        }
        //将图片输出到Servlet输出流中
        // 将buffImg写入sos（response）中
        try {
            ImageIO.write(buffImg, byId.getType(), sos);
        } catch (IOException e) {
            log.warn("图片{}响应失败，msg：{}",buffImg,e.getMessage());
        }
    }

    /**
     * 用户rating积分添加 ，属于内部接口
     * @param rating
     * @param userId
     * @return
     */
    @PostMapping("/addRating/{id}")
    @AuthAnnotation({Auth.ROOT})
    @ResponseBody
    public ResponseResult addRating(@RequestParam Integer rating,@PathVariable("id") String userId){
        userService.addRating(userId,rating);
        return ResponseResult.success();
    }

    /**
     * 获取用户rating积分排名
     * @param userId
     * @return
     */
    @PostMapping("/rating/rank/{id}")
    @AuthAnnotation({Auth.ROOT})
    @ResponseBody
    public ResponseResult getuserRatingRank(@PathVariable("id") String userId){
        Object rank = userService.getUserRatingRank(userId);
        return ResponseResult.success().setData(rank);
    }

    /**
     * 积分排行榜
     * @param page
     * @param size
     * @return
     */
    @PostMapping("/rating")
    @ResponseBody
    public ResponseResult rating(Integer page,Integer size){
        if(page==null||page<1)page = 1;
        if(size==null)size = 10;
        RequestUserParams requestUserParams = new RequestUserParams();
        requestUserParams.setField("rating");
        requestUserParams.setOrder(RequestParams.DESC);
        requestUserParams.setPage(page);
        requestUserParams.setSize(size);
        PageResult<User> search = userService.search(requestUserParams);
        for (User user : search.getDataList()) {
            user.setPassword(null);
            user.setAuths(null);
            user.setStatus(null);
            user.setPhone(null);
            user.setNumber(null);
            user.setEmail(null);
        }
        return ResponseResult.success().setData(search);
    }

}
